<template>
  <el-card style="width: 100%; border-radius: 4px">
    <GapedColumn width="100%">
      <OptionFields
        v-model="selectedFields"
        :option-fields="optionFields"
        :table-name="tableName"
        :applyStorage="applyStorage"
      />
      <el-form :model="formData" label-position="top" style="width: 99%">
        <el-row :gutter="20">
          <el-col
            v-for="(field, index) in searchFields"
            :key="index"
            :md="field.colSpan || 6"
            :sm="12"
            :xs="24"
          >
            <el-form-item>
              <template #label>
                <div class="label-container">
                  <span>{{ field.label }}</span>
                  <el-popover
                    placement="bottom-start"
                    trigger="click"
                    :width="200"
                  >
                    <template #reference>
                      <el-tag class="operator-tag" size="small" @click.stop>
                        {{ field.operator || defaultOperator }}
                      </el-tag>
                    </template>
                    <el-select
                      v-model="field.operator"
                      placeholder="选择操作符"
                      size="small"
                      @change="handleOperatorChange(field)"
                    >
                      <el-option
                        v-for="op in getOperatorsByFieldType(field.field_type)"
                        :key="op"
                        :label="op"
                        :value="op"
                      />
                    </el-select>
                  </el-popover>
                </div>
              </template>
              <component
                :is="getComponentType(field.type)"
                v-model="formData[field.name]"
                :placeholder="field.placeholder || field.label"
                :clearable="field.clearable !== false"
                v-bind="field.props || {}"
              >
                <template v-if="field.type === 'select'">
                  <el-option
                    v-for="option in field.options || []"
                    :key="option.value"
                    :label="option.label"
                    :value="option.value"
                  />
                </template>
              </component>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
    </GapedColumn>
  </el-card>
</template>

<script setup lang="ts">
import { map } from 'lodash'
import { ref, reactive, watch, onMounted, computed } from 'vue'
import { GapedColumn } from '@/core/components'
import type {
  SearchField,
  OptionField,
  SearchParam,
  WarningConfigItem,
} from '@/models/warning'
import {
  defaultOperator,
  operatorValues,
  fieldTypeOperatorMapping,
} from '@/models/warning'
import OptionFields from './OptionFields.vue'

interface Props {
  tableName: string
  optionFields: Array<OptionField>
  existingParams?: Array<WarningConfigItem>
  applyStorage?: boolean
}

const props = defineProps<Props>()

const selectedFields = ref<Array<string>>(map(props.existingParams, 'name'))

const fields = computed<Array<SearchField>>(() => {
  return selectedFields.value
    .map(fieldName =>
      props.optionFields.find(field => field.name === fieldName)
    )
    .filter(Boolean)
    .sort((a, b) => {
      if (a?.alwaysSelected && !b?.alwaysSelected) return 1
      if (!a?.alwaysSelected && b?.alwaysSelected) return -1
      return 0
    })
})
const searchFields = computed<Array<SearchField>>(() => {
  return fields.value.map(field => {
    if (field.type === 'daterange') {
      return {
        ...field,
        props: {
          ...field.props,
          type: 'daterange',
          'value-format': 'YYYY-MM-DD',
        },
        operator: 'between',
      }
    }
    return {
      ...field,
      operator: field.operator || defaultOperator,
    }
  })
})

const formData = reactive<Record<string, any>>({})

const getOperatorsByFieldType = (fieldType: string) => {
  return (
    fieldTypeOperatorMapping[
      fieldType as keyof typeof fieldTypeOperatorMapping
    ] || operatorValues
  )
}

// 初始化formData和operator
const initFormData = () => {
  if (props.existingParams && props.existingParams.length > 0) {
    props.existingParams.forEach(param => {
      formData[param.name] = param.value
      const field = fields.value.find(f => f.name === param.name)
      if (field && param.operator) {
        field.operator = param.operator
      }
    })
  }
}

const getComponentType = (type: string) => {
  switch (type) {
    case 'input':
      return 'el-input'
    case 'select':
      return 'el-select'
    case 'date':
    case 'daterange':
      return 'el-date-picker'
    default:
      return type
  }
}

const handleOperatorChange = (field: SearchField) => {
  // 当操作符改变时，可能需要重置字段值
  if (field.operator === 'between' && !Array.isArray(formData[field.name])) {
    formData[field.name] = ['', '']
  }
}

// 获取字段值并进行处理
const getFieldValue = (field: SearchField) => {
  let value = formData[field.name]

  // 处理between和in操作符的值转换
  if (value !== undefined && value !== null && value !== '') {
    if (field.operator === 'between' || field.operator === 'in') {
      if (!Array.isArray(value)) {
        value = [value]
      }
    }
  }

  return value
}

// 生成搜索参数
const generateSearchParams = (): Array<SearchParam> => {
  const params: Array<SearchParam> = []
  for (const field of searchFields.value) {
    const value = getFieldValue(field)
    params.push({
      ...field,
      name: field.name,
      value,
      operator: field.operator || defaultOperator,
    })
  }
  return params
}

// 初始化或更新select字段的options
const updateSelectOptions = async () => {
  for (const field of fields.value) {
    if (field.type === 'select' && field.getValue) {
      const value = formData[field.name]
      const result = await field.getValue(value)
      if (Array.isArray(result)) {
        field.options = result
      }
    }
  }
}

// 初始化时调用
onMounted(() => {
  initFormData()
  updateSelectOptions()
})

// 监听fields变化
watch(
  fields,
  () => {
    updateSelectOptions()
  },
  { deep: true }
)

defineExpose({
  generateSearchParams,
  resetForm: () => {
    Object.keys(formData).forEach(key => {
      formData[key] = Array.isArray(formData[key]) ? ['', ''] : ''
    })
  },
})
</script>

<style scoped>
.search-form {
  border-radius: 4px;
}

.el-form-item {
  margin-bottom: 16px;
}

.label-container {
  display: flex;
  align-items: center;
  gap: 8px;
}

.operator-tag {
  cursor: pointer;
  margin-left: 4px;
}
</style>
